package com.base.themvx.adapter

import android.content.Context
import android.util.SparseArray
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.annotation.DrawableRes
import androidx.annotation.LayoutRes
import androidx.annotation.StringRes
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModelStoreOwner
import androidx.recyclerview.widget.RecyclerView
import com.base.themvx.R
import com.base.themvx.utils.ImageUtil
import com.base.themvx.vm.BaseViewModel
import com.base.themvx.vm.ViewModelsProviderFactory.getViewModel
import com.chad.library.adapter.base.viewholder.BaseViewHolder

/**
 * 统一的　RecycleView的　适配器的　ViewHolder
 * @date 2022-02-16
 */
abstract class ACommonViewHolder<D>(parentView: ViewGroup, @LayoutRes itemViewLayoutRes: Int) :
    BaseViewHolder(
        LayoutInflater.from(parentView.context).inflate(itemViewLayoutRes, parentView, false)
    ) {
    protected val TAG = javaClass.simpleName
    protected val mContext: Context by lazy(LazyThreadSafetyMode.NONE) {
        itemView.context
    }
    protected var mHostAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>? = null

    /**
     * 便捷的供子类可能需要 重新设置视图的 [LayoutParams]时使用
     */
    protected val WRAP_CONTENT by lazy(LazyThreadSafetyMode.NONE) {
        ViewGroup.LayoutParams.WRAP_CONTENT
    }

    /**
     * 便捷的供子类可能需要 重新设置视图的 [LayoutParams]时使用
     */
    protected val MATCH_PARENT by lazy(LazyThreadSafetyMode.NONE) {
        ViewGroup.LayoutParams.MATCH_PARENT
    }

    /**
     * 当前的 ViewHolder 对应绑定的 数据
     */
    protected var mItemData: D? = null

    /**
     * 内存缓存的 本 itemView 的各子视图，为了减少 View树的遍历
     */
    protected var cachedViews: SparseArray<View>? = null

    init {
        if (parentView is RecyclerView) {
            mHostAdapter = parentView.adapter
        }
        initViews()
    }

    /**
     * 初始化 本 itemView 的 子视图
     * 注：该方法是在 构造函数 中调用的,还不能在里面访问 本类的 成员属性
     */
    protected open fun initViews() {
        //说明:空实现、不处理
    }

    /**
     * 如果不使用 [ViewBinding] 的场景下，使用此方法 获取 本 ViewHolder 对应的子视图
     */
    open fun <V : View> view(theViewId: Int): V {
        cachedViews?.get(theViewId)?.let {
            return it as V
        }
        val theView = itemView.findViewById<V>(theViewId) //如果 theView == null 会抛出异常
        if (theView != null) {
            if (cachedViews == null) {
                cachedViews = SparseArray()
            }
            cachedViews?.put(theViewId, theView)
        }
        return theView
    }

    fun getString(@StringRes strRes: Int): String {
        return mContext.getString(strRes)
    }

    fun getString(@StringRes strRes: Int, vararg args: Any): String {
        return mContext.getString(strRes, args)
    }


    protected fun <AD : RecyclerView.Adapter<*>> peekHostAdapterAsDesired(): AD? {
        if (mHostAdapter == null) {
            return null
        }
        return mHostAdapter as AD
    }

    protected fun peekHostAdapterAsSelectAdapter(): AbsSelectableAdapter<D,*>? {
        return peekHostAdapterAsDesired()
    }

    /**
     *  [ViewHolder] 内 来获取 当前 适配器(Adapter)所在宿主 的 [ViewModel]
     *  注：因为 [ViewHolder] 内的 [mContext] 上下文只可以溯源到最近层的,即为 当前 Activity 内的 [ViewModel]
     *  注：不推荐如此使用
     */
    protected fun <VM : BaseViewModel> getHostViewModel(viewModelClass: Class<VM>): VM? {
        var curLifecycleOwner: ViewModelStoreOwner? = null
        if (mContext is FragmentActivity) {
            val a: FragmentActivity = mContext as FragmentActivity
            curLifecycleOwner = a
        }
        return curLifecycleOwner?.let {
            getViewModel(it,viewModelClass)
        }
    }

    /**
     * 判断 当前 位置的 viewHolder/itemView 是否需要可点击的
     * def = [itemView.isEnabled] //所以具体的 itemView在 xml中就可以提前表明本 itemView不可点击
     * 注：本方法 是在[onBindView] 之前调用
     */
    open fun isViewHolderClickable(): Boolean {
        return itemView.isEnabled
    }

    /**
     * 提供 可代替 itemView 来行使 item点击的 View
     * def = itemView自身
     */
    open fun providedReplaceItemClickView(): View {
        return itemView
    }

    open fun onBindView(item: D?, payloads: List<Any>) {
        mItemData = item
        onBindView(item)
    }

    abstract fun onBindView(item: D?)

    /**
     * 加载图片
     */
    protected fun loadImg(
        ivImag: ImageView,
        imgUrl: String?,
        @DrawableRes holderImgRes: Int
    ) {
        if (imgUrl.isNullOrBlank()) {
            return
        }
        ImageUtil.loadImage(mContext, imgUrl, holderImgRes, holderImgRes, ivImag)
    }
}